package com.dzirtbry.ticatac.pane;

import java.awt.Point;
import java.util.ArrayList;

public class TicTacPane {
	private int[][] pane;
	
	public TicTacPane() {
		pane = new int[3][3];
	}
	
	public int getVictorious() {
		for (int i=0; i<3; i++) {
			if (isColumnLine(i, TicTacMarker.TIC) || isRowLine(i, TicTacMarker.TIC)) 
				return TicTacMarker.TIC;
			if (isColumnLine(i, TicTacMarker.TAC) || isRowLine(i, TicTacMarker.TAC)) 
				return TicTacMarker.TAC;
		}
		if (checkMainDiagonal() != TicTacMarker.NO)
			return checkMainDiagonal();
		if (checkCounterDiagonal() != TicTacMarker.NO)
			return checkCounterDiagonal();
		return TicTacMarker.NO;
	}
	
	private int checkMainDiagonal() {
		if (pane[0][0] == TicTacMarker.NO) {
			return TicTacMarker.NO;
		}
		int res = pane[0][0];
		if ((pane[1][1] == res) &&(pane[2][2] == res))
			return res;
		else 
			return TicTacMarker.NO;
	}
	
	private int checkCounterDiagonal() {
		if (pane[0][2] == TicTacMarker.NO) {
			return TicTacMarker.NO;
		}
		int res = pane[0][2];
		if ((pane[1][1] == res) && (pane[2][0] == res))
			return res;
		else 
			return TicTacMarker.NO;
	}
	
	public boolean isMoveAvaliable() {
		return getFreePoints().size() != 0;
	}
	
	public boolean isMoveAvaliable(Point point) {
		return pane[point.x][point.y] == 0;
	}
	
	public ArrayList<Point> getFreePoints () {
		ArrayList<Point> res = new ArrayList<Point>();
		for (int i=0; i<3; i++) {
			for (int j=0; j<3; j++) {
				if (this.getMarker(new Point(i, j)) == TicTacMarker.NO) 
					res.add(new Point(i, j));
			}
		}
		return res;
	}
	
	public int get (int x, int y) {
		return pane[x][y];
	}
	
	/**
	 * Sets specified <code>marker</code> to the <code>point</code> of the pane
	 * 
	 * @param marker TicTacMarker
	 * @param point Pane coordinates 
	 * 
	 */
	public void setMarker (Point point, int marker) {
		pane[point.x][point.y] = marker; 
	}
	
	/**
	 * Check if row is marked in any position
	 * 
	 * @param row Row number (0..2)
	 * @return True is <code>pane</code> in row <code>row</code> is not
	 * marked, false otherwise
	 */
	public boolean isRowFree (int row) {
		return isRowLine(row, TicTacMarker.NO);
	}
	
	/**
	 * Check if column is marked in any position 
	 * 
	 * @param col Column number (0..2)
	 * @return True is <code>pane</code> in column <code>col</code> is not
	 * marked, false otherwise
	 */
	public boolean isColumnFree (int col) {
		return isColumnLine(col, TicTacMarker.NO);
	}
	
	public boolean isColumnLine(int col, int marker) {
		for (int i=0; i<3; i++) {
			if (pane[i][col] != marker) {
				return false;
			}
		}
		return true;
	}
	
	public boolean isRowLine (int row, int marker) {
		for (int i=0; i<3; i++) {
			if (pane[row][i] != marker) {
				return false;
			}
		}
		return true;
	}
	
	/**
	 * Check if row is victory-avaliable
	 * 
	 * @param row Row number (0..2)
	 * @param marker TicTacMarker
	 * @return True is <code>pane</code> in row <code>row</code> is not
	 * marked or marked with <code>marker</code>, false otherwise
	 */
	public boolean isRowAvaliable (int row, int marker) {
		for (int i=0; i<3; i++) {
			if ((pane[row][i] != TicTacMarker.NO) && (pane[row][i] != marker)) {
				return false;
			}
		}
		return true;
	}
	
	/**
	 * Check if column is victory-avaliable
	 * 
	 * @param col column number (0..2)
	 * @param marker TicTacMarker
	 * @return True is <code>pane</code> in column <code>col</code> is not
	 * marked or marked with <code>marker</code>, false otherwise
	 */
	public boolean isColAvaliable (int col, int marker) {
		for (int i=0; i<3; i++) {
			if ((pane[i][col] != TicTacMarker.NO) && (pane[i][col] != marker)) {
				return false;
			}
		}
		return true;
	}
	
	public boolean isMainDiagonalAvaliable (int marker) {
		for (int i=0; i<3; i++) {
			if ((pane[i][i] != TicTacMarker.NO) && (pane[i][i] != marker)) {
				return false;
			}
		}
		return true;
	}
	
	public boolean isCounterDiagonalAvaliable (int marker) {
		for (int i=0; i<3; i++) {
			if ((pane[i][2-i] != TicTacMarker.NO) && (pane[i][2-i] != marker)) {
				return false;
			}
		}
		return true;
	}
	
	public boolean isPointOnMainDiagonal(Point point) {
		for (int i = 0; i<3; i++) {
			if (point.equals(new Point(i, i)))
				return true;
		}
		return false;
	}
	
	public boolean isPointOnCounterDiagonal(Point point) {
		for (int i = 0; i<3; i++) {
			if (point.equals(new Point(i, 2-i)))
				return true;
		}
		return false;
	}
	
	public int getMarker (Point point) {
		return pane[point.x][point.y];
	}
	
	public void print () {
		System.out.println("Current pane state");
		for (int i=0; i<3; i++) {
			for (int j=0; j<3; j++) {
				char c = 0;
				switch (pane[i][j]) {
				case 0: c='-'; break;
				case 1: c='X'; break;
				case 2: c='O'; break;
				default: break;
				}
				System.out.print(c + " ");
			}
			System.out.println();
		}
	}
}
